/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.launch.constant.TokenConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.admin.dto.TaskPlanPageQueryDTO;
import org.springblade.modules.admin.entity.MaintainTemplate;
import org.springblade.modules.admin.entity.MaintainTemplateRelation;
import org.springblade.modules.admin.entity.MaintainTemplateSceneRelation;
import org.springblade.modules.admin.enums.TaskStatusEnum;
import org.springblade.modules.admin.service.IMaintainTemplateSceneRelationService;
import org.springblade.modules.admin.service.MaintainTemplateRelationService;
import org.springblade.modules.admin.service.MaintainTemplateService;
import org.springblade.modules.admin.mapper.MaintainTemplateMapper;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.modules.admin.vo.TemplateDetailVO;
import org.springblade.modules.admin.vo.TemplateSelectDownVO;
import org.springblade.modules.admin.vo.TemplateVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 保养模板 服务实现类
 *
 * @author zcc
 * @since 2021-09-24
 */
@Service
public class MaintainTemplateServiceImpl extends BaseServiceImpl<MaintainTemplateMapper, MaintainTemplate> implements MaintainTemplateService {

	@Autowired
	private MaintainTemplateRelationService templateRelationService;
	@Autowired
	private IMaintainTemplateSceneRelationService templateSceneRelationService;

	@Value("${project.api.url.maintain}")
	private String maintainApiUrl;

	@Override
	public List<TemplateSelectDownVO> getTemplateSelectDown(String planType, String keyword, List<Long> taskPlanIds, List<Long> sceneTypeIds) {
		List<String> tenantIds = new ArrayList<>();
		tenantIds.add(AuthUtil.getTenantId());
		tenantIds.add(BladeConstant.ADMIN_TENANT_ID);
		return baseMapper.getTemplateSelectDown(planType,tenantIds,keyword,taskPlanIds,sceneTypeIds);
	}

	@Override
	public IPage<TemplateVO> selectTemplatePage(TaskPlanPageQueryDTO pageQueryDTO,IPage<TemplateVO> page) {
		List<String> tenantIds = new ArrayList<>();
		tenantIds.add(AuthUtil.getTenantId());
		tenantIds.add(BladeConstant.ADMIN_TENANT_ID);
		return page.setRecords(baseMapper.selectTemplatePage(pageQueryDTO,tenantIds,page));
	}

	@Override
	public TemplateDetailVO selectTemplateDetail(Long id) {
		return baseMapper.selectTemplateDetail(id);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean copy(Long id) {

		MaintainTemplate oldTemplate = this.getById(id);
		MaintainTemplate newTemplate = new MaintainTemplate();
		BeanUtil.copyProperties(oldTemplate,newTemplate, "id","tenantId","createTime","createUser","updateTime","updateUser","createDept","status","isDeleted");
		String newName = oldTemplate.getName()+"—复制"+ String.format("%04d",new Random().nextInt(9999));
		newTemplate.setName(newName);
		newTemplate.setTenantId(AuthUtil.getTenantId());
		this.save(newTemplate);

		List<MaintainTemplateSceneRelation> oldTemplateSceneRelation = templateSceneRelationService.list(Wrappers.<MaintainTemplateSceneRelation>lambdaQuery().eq(MaintainTemplateSceneRelation::getTemplateId,id));
		List<MaintainTemplateSceneRelation> newTemplateSceneRelation = new ArrayList<>();
		oldTemplateSceneRelation.forEach(e -> {
			MaintainTemplateSceneRelation templateSceneRelation = new MaintainTemplateSceneRelation();
			BeanUtil.copyProperties(e,templateSceneRelation, "id","tenantId","createTime","createUser","updateTime","updateUser","createDept","status","isDeleted");
			templateSceneRelation.setTemplateId(newTemplate.getId());
			templateSceneRelation.setTenantId(AuthUtil.getTenantId());
			newTemplateSceneRelation.add(templateSceneRelation);
		});
		templateSceneRelationService.saveBatch(newTemplateSceneRelation);

		List<MaintainTemplateRelation> oldTemplateRelation = templateRelationService.list(Wrappers.<MaintainTemplateRelation>lambdaQuery().eq(MaintainTemplateRelation::getTemplateId,id));
		List<MaintainTemplateRelation> newTemplateRelation = new ArrayList<>();
		oldTemplateRelation.forEach(e -> {
			MaintainTemplateRelation templateRelation = new MaintainTemplateRelation();
			BeanUtil.copyProperties(e,templateRelation, "id","tenantId","createTime","createUser","updateTime","updateUser","createDept","status","isDeleted");
			templateRelation.setTemplateId(newTemplate.getId());
			templateRelation.setTenantId(AuthUtil.getTenantId());
			newTemplateRelation.add(templateRelation);
		});
		templateRelationService.saveBatch(newTemplateRelation);
		return Boolean.TRUE;
	}

	@Override
	public Object selectElevatorCount(Long templateId, String contentIds) {
		HashMap<String, Integer> resultMap = new HashMap<>();
		if(ObjectUtil.isNotNull(templateId)){
			Integer elevatorCount = baseMapper.selectElevatorCountByTemplate(templateId);
			resultMap.put("elevatorCount",elevatorCount);
			Integer planCount = baseMapper.selectPlanCountByTemplate(templateId);
			resultMap.put("planCount",planCount);
		}
		if(ObjectUtil.isNotEmpty(contentIds)){
			Integer elevatorCount = baseMapper.selectElevatorCountByTemplateContent(Func.toLongList(contentIds));
			resultMap.put("elevatorCount",elevatorCount);
		}
		return resultMap;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public TemplateDetailVO saveTemplate(MaintainTemplate template) {
		super.save(template);
		if(Func.isNotEmpty(template.getSceneTypeId())){
			MaintainTemplateSceneRelation templateSceneRelation = new MaintainTemplateSceneRelation();
			templateSceneRelation.setTemplateId(template.getId());
			templateSceneRelation.setSceneTypeId(template.getSceneTypeId());
			templateSceneRelationService.save(templateSceneRelation);
		}
		return this.selectTemplateDetail(template.getId());
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean updateTemplate(MaintainTemplate template) {
		templateSceneRelationService.remove(Wrappers.<MaintainTemplateSceneRelation>lambdaQuery().eq(MaintainTemplateSceneRelation::getTemplateId,template.getId()));
		if(Func.isNotEmpty(template.getSceneTypeId())){
			MaintainTemplateSceneRelation templateSceneRelation = new MaintainTemplateSceneRelation();
			templateSceneRelation.setTemplateId(template.getId());
			templateSceneRelation.setSceneTypeId(template.getSceneTypeId());
			templateSceneRelationService.save(templateSceneRelation);
		}
		return super.updateById(template);
	}

	@Override
	public List<TemplateSelectDownVO> selectTemplateDownByPlanStatus(Integer planStatus,String applyElevatorType, String keyword, List<Long> taskPlanIds, List<Long> sceneTypeIds) {
		if(planStatus.equals(TaskStatusEnum.BY_DISABLE.getStatus())){
			List<String> tenantIds = new ArrayList<>();
			tenantIds.add(AuthUtil.getTenantId());
			tenantIds.add(BladeConstant.ADMIN_TENANT_ID);
			return baseMapper.getTemplateSelectDown(applyElevatorType,tenantIds,keyword, taskPlanIds,sceneTypeIds);
		}else {
			List<String> tenantIds = new ArrayList<>();
			tenantIds.add(AuthUtil.getTenantId());
			return baseMapper.selectTemplateHistorySelectDown(tenantIds,keyword);
		}
	}

	@Override
	public Boolean removeTemplate(List<Long> toLongList) {
		return templateSceneRelationService.remove(Wrappers.<MaintainTemplateSceneRelation>lambdaQuery().in(MaintainTemplateSceneRelation::getTemplateId,toLongList))
			&& super.removeByIds(toLongList);
	}

	@Override
	public String generateWxAppCode(Long templateId) {
		String url = "/maintain/template/history/generateWxAppCode";
		Map<String, Object> paramMap = new HashMap<>(2);
		paramMap.put("templateId", templateId);
		HttpServletRequest request = WebUtil.getRequest();
		String token = AuthUtil.getHeader(request);
		paramMap.put(TokenConstant.HEADER, token);
		String result = null;
		try {
			result = HttpUtil.get(maintainApiUrl + url, paramMap, 10000);
		} catch (IORuntimeException e) {
			throw new ServiceException("获取小程序码异常!");
		}

		JSONObject jsonObject = JSONUtil.parseObj(result);
		if (Func.toInt(jsonObject.get("code")) != 200) {
			throw new ServiceException("获取小程序码异常!");
		}

		return Func.toStr(jsonObject.get("data"), null);
	}

	@Override
	public List<TemplateSelectDownVO> selectTemplateDownByName(String planType, String keyword, List<Long> taskPlanIds) {
		List<String> tenantIds = new ArrayList<>();
		tenantIds.add(AuthUtil.getTenantId());
		tenantIds.add(BladeConstant.ADMIN_TENANT_ID);
		return baseMapper.selectTemplateDownByName(planType,tenantIds,keyword,taskPlanIds);
	}

	@Override
	public List<TemplateSelectDownVO> selectByPlan(Long planId) {
		List<String> tenantIds = new ArrayList<>();
		tenantIds.add(AuthUtil.getTenantId());
		tenantIds.add(BladeConstant.ADMIN_TENANT_ID);
		return baseMapper.selectByPlan(tenantIds,planId);
	}
}



